<template>
    <div>
        <el-form-item v-if="select" :label="label">
            <models-select
                v-model="currModel"
                :type="type"
                @change="changeModel"
            />
        </el-form-item>

        <template v-for="(conf, index) in configArray" :key="conf.key">
            <el-form-item v-if="conf.type === 'slider'" :label="conf.name" :prop="conf.key">
                <template #label>
                    <span class="mr-[4px] mt-[2px]">{{ conf.name }}</span>
                    <el-tooltip
                        class="box-item"
                        effect="dark"
                        :content="conf.key + ': ' + conf.tips"
                        placement="right"
                    >
                        <icon :size="16" name="el-icon-QuestionFilled" />
                    </el-tooltip>
                </template>
                <div class="flex items-center gap-x-5 w-[100%] mb-4">
                    <el-switch
                        v-if="conf.status !== undefined"
                        v-model="conf.status"
                        size="small"
                        @change="changeStatus($event, index)"
                    />

                    <div
                        v-if="!conf.status"
                        class="flex items-center w-full h-[32px]"
                    >
                        <el-slider
                            :model-value="conf.range[1]"
                            :min="conf.range[0]"
                            :max="conf.range[1]"
                            :disabled="true"
                            :show-tooltip="false"
                            class="mr-[30px]"
                        />
                        <el-input-number :disabled="true" class="shrink-0" />
                    </div>
                    <el-slider
                        v-else
                        v-model="conf.default"
                        :min="conf.range[0]"
                        :max="conf.range[1]"
                        :step="conf.step"
                        show-input
                    />
                </div>
            </el-form-item>
            <el-form-item v-if="conf.type === 'switch'" :label="conf.name" :prop="conf.key">
                <template #label>
                    <span class="mr-[4px] mt-[2px]">{{ conf.name }}</span>
                    <el-tooltip
                        class="box-item"
                        effect="dark"
                        :content="conf.key + ': ' + conf.tips"
                        placement="right"
                    >
                        <icon :size="16" name="el-icon-QuestionFilled" />
                    </el-tooltip>
                </template>
                <el-switch v-model="conf.default" />
            </el-form-item>
        </template>

        <el-form-item v-if="tplParams.func !== undefined" label="函数调用">
            <template #label>
                <span class="mr-[4px] mt-[2px]">函数调用</span>
                <el-tooltip
                    class="box-item"
                    effect="dark"
                    content="模型是否支持 Function calling，如果不支持则无法使用Mcp功能。"
                    placement="right"
                >
                    <icon :size="16" name="el-icon-QuestionFilled" />
                </el-tooltip>
            </template>
            <el-tag v-if="tplParams.func" type="success">支持</el-tag>
            <el-tag v-else type="info">不支持</el-tag>
        </el-form-item>
    </div>
</template>

<script setup lang="ts">
import { throttle } from 'lodash-es'
import useAppStore from '@/stores/modules/app'
import type { ModelConfigType, ModelParamsType } from './type.ts'

const emits = defineEmits(['change', 'update:modelValue'])
const props = defineProps({
    // 模型名称: zhipu:glm-4.5
    modelValue: {
        type: String,
        default: ''
    },

    // 模型参数: {top_p: 1.0,...}
    params: {
        type: Object,
        default: () => {}
    },
    // 下拉框: true=显示,false=隐藏
    select: {
        type: Boolean,
        default: true
    },
    // 项目目
    label: {
        type: String,
        default: 'AI模型'
    },
    // 模型类型: [chat,vector,ranking]
    type: {
        type: String,
        default: 'chat'
    }
})

const appStore = useAppStore()

// 模型名称(m:s)
const currModel = ref<string>('')
// 当前模型配置模板
const tplConfig = ref<ModelConfigType[]>([])
// 当前模型参数模板
const tplParams = ref<ModelParamsType>({})
// 新的模型配置数组
const configArray = ref<ModelConfigType[]>([])

/**
 * 切换模型
 *
 * @param data
 * @author zero
 */
const changeModel = (data: any) => {
    currModel.value = data.name
    emits('update:modelValue', data.name)
}

/**
 * 切换状态
 *
 * @param {boolean} status
 * @param {number} index
 * @author zero
 */
const changeStatus = (status: any, index: number) => {
    if (status) {
        configArray.value[index]!.default = tplConfig.value[index]?.default
    } else {
        configArray.value[index]!.default = null
    }
}

/**
 * 格式化配置项
 *
 * @param {string} models - zhipu:glm-4.5
 * @param {any} params - {context_num: 1, temperature: 0.1}
 * @param {boolean} isSwitch - 模型切换
 * @author zero
 */
const formatConfigs = (models: string, params: any, isSwitch: boolean = false) => {
    configArray.value = []
    if (models) {
        const modelArray: string[] = models.split(':')
        const marks: string = modelArray[0] || ''
        const model: string = modelArray[1] || ''

        let nodes: any[]
        switch (props.type) {
            case 'vector':
                nodes = appStore.models.chat_models
                break
            case 'ranking':
                nodes = appStore.models.ranking_models
                break
            default:
                nodes = appStore.models.chat_models
        }

        for (let i = 0; i < nodes.length; i++) {
            const item = nodes[i]
            if (item.mark === marks) {
                tplConfig.value = JSON.parse(JSON.stringify(item.config))
                for (let k = 0; k < nodes[i].models.length; k++) {
                    const m = nodes[i].models[k]
                    if (m.model === model) {
                        tplParams.value = JSON.parse(JSON.stringify(m))
                        break
                    }
                }
                break
            }
        }

        const newConfigs: ModelConfigType[] = []
        const oldConfigs = JSON.parse(JSON.stringify(tplConfig.value))
        oldConfigs.forEach((item: ModelConfigType) => {
            if (!isSwitch) {
                item.default = params[item.key] ?? null
                if (item.status !== undefined) {
                    item.status = item.default !== null
                }
            } else {
                if (item.status !== undefined && !item.status) {
                    item.default = null
                }
            }
            if (item.key === 'max_tokens' && tplParams.value.max_tokens) {
                item.range[1] = tplParams.value.max_tokens
            }
            if (!(item.key === 'think' && !tplParams.value.think)) {
                newConfigs.push(item)
            }
        })

        configArray.value = newConfigs
    }
}

/**
 * 节流通知更新
 */
const throttledCallback = throttle(() => {
    let parameter: Record<string, any> = {}
    configArray.value.forEach((item: ModelConfigType) => {
        parameter[item.key] = item.default
    })
    emits('change', {
        models: currModel.value,
        params: parameter
    })
}, 300)

/**
 * 监听参数变动
 */
watch(
    () => configArray.value,
    () => {
        throttledCallback()
    },
    { deep: true }
)

/**
 * 监听模型传参
 */
watch(
    () => props.modelValue,
    (val: string) => {
        let isSwitch: boolean = false
        if (currModel.value && currModel.value !== val) {
            isSwitch = true
        }
        currModel.value = val
        formatConfigs(val, props.params, isSwitch)
    }, { immediate: true }
)
</script>
